package uk.co.fullerlee.vicoid20;

import java.util.Observable;
import java.util.Observer;

import emulator.GUI.display.VicDisplay;
import emulator.GUI.display.VicDisplayRegistry;
import emulator.GUI.display.VicScreen;
import uk.co.fullerlee.vicoid20.widget.Vicoid20ScreenView;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class Vicoid20Thread extends Thread{
	private boolean has_changed = false;
	private boolean mRun;
	private SurfaceHolder mSurfaceHolder;
	private Handler mHandler;
	public Context mContext;
	private Vicoid20ScreenView vicoid20ScreenView;
	
	private int mCanvasWidth;
	private int mCanvasHeight;
	private VicScreen vicScreen;
	
	private Paint bitmapFilterPaint;
	
	public Vicoid20Thread(SurfaceHolder surfaceHolder, Context context, Handler handler, Vicoid20ScreenView vicoid20ScreenView) {
			
			Thread.currentThread().setName("View Thread");
		
			mSurfaceHolder = surfaceHolder;
			mHandler = handler;
			mContext = context;
			this.vicoid20ScreenView = vicoid20ScreenView;
			
			vicScreen = new VicScreen(1, VicDisplay.MAX_SCREEN_WIDTH, 1, VicDisplay.MAX_SCREEN_HEIGHT);
			vicScreen.addObserver(new ScreenObserver());
			
			mCanvasWidth = 320;
			mCanvasHeight = 480;
			
			VicDisplayRegistry.registerDisplay("VicScreen", vicScreen);
			
			bitmapFilterPaint = new Paint();
			bitmapFilterPaint.setFilterBitmap(true);
			bitmapFilterPaint.setAntiAlias(true);
			
			System.gc();
	}
	
	public void setSurfaceSize(int width, int height) {
		// synchronized to make sure these all change atomically
		synchronized (mSurfaceHolder) {
			mCanvasWidth = width;
			mCanvasHeight = height;
			
			Log.d(Vicoid20Main.LOGTAG, "Surface size changed to: " + width + ", " + height);
		}
	}
	
	public boolean onTouchEvent(MotionEvent me) {
		// Test if on board

		synchronized (mSurfaceHolder) {
			
		}
		
		return true;
	}
	
	private void doDraw(Canvas canvas) {
		//clear screen
		
		//backBufferCanvas.drawBitmap(mBackgroundImage, 0, 0, null);

		////////////////////
		//Clip to board-area to Draw Board
		////////////////////
		//canvas.clipRect(0, 0/*WordingoSettings.cellHeight*/, WordingoSettings.screenWidth, WordingoSettings.screenWidth+WordingoSettings.cellHeight, Region.Op.REPLACE);

		//Log.d(Vicoid20Main.LOGTAG, "in dodraw: ");
		
		//canvas.drawARGB(100, (int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255));
		
		//canvas.drawBitmap(vicScreen.getScreenBitmap(), 0,0, null);
		
		
		canvas.drawBitmap(vicScreen.getScreenBitmap(), 
							new Rect(0, 0, vicScreen.getScreenBitmap().getWidth(), vicScreen.getScreenBitmap().getHeight()),
							new Rect(0,0,mCanvasWidth, Math.min(mCanvasHeight, vicScreen.getScreenBitmap().getHeight())),
							bitmapFilterPaint);
		
	}
	
	public void run() {
		
		while (mRun) {
			Canvas c = null;
			try {
				c = mSurfaceHolder.lockCanvas(null);
				
				waitChanged();
				synchronized (mSurfaceHolder) {
					doDraw(c);
				}
				ackChange();
			} 
			finally {
				// do this in a finally so that if an exception is thrown
				// during the above, we don't leave the Surface in an
				// inconsistent state
				if (c != null) {
					mSurfaceHolder.unlockCanvasAndPost(c);
				}
			}
		}
		
		//recycle all the images
		recycleBitmaps();
	}
	
	private void recycleBitmaps() {
		// TODO Auto-generated method stub
		
	}

	public void setRunning(boolean b) {
		mRun = b;
	}
	
	public void printState() {
		Log.d(Vicoid20Main.LOGTAG, "Printing State in Vicoid20Thread");
	}

	public class ScreenObserver implements Observer {

		@Override
		public void update(Observable observable, Object data) {
			setChanged();
		}

	}

	private synchronized void waitChanged() {
		try {
			while (!has_changed)
					wait();
		} catch (InterruptedException e) {
			/* NOP */
		}
	}

	private synchronized void setChanged() {
		has_changed = true;
		notify();
	}

	private synchronized void ackChange() {
		has_changed = false;
	}
}
